﻿using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Linq;
using System.IO;
using System.Collections.Generic;
using Styx.Common;
using System.Net;
using System.Diagnostics;

namespace KingWoW
{
    public class SvnManager
    {
        private const string DB = "wc.db";
        private const string PATTERN = "/!svn/ver/(?'version'[0-9]*)/";
        private const string SvnUrl = "http://king-wow.googlecode.com/svn/trunk/";
        private readonly Regex LinkPattern = new Regex(@"<li><a href="".+"">(?<ln>.+(?:..))</a></li>",
            RegexOptions.CultureInvariant);
        private string basePath;

        public SvnManager()
        {
            basePath = Path.Combine(Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName),
                @"Routines\king-wow\");
        }

        private int OnlineRevisionNumber()
        {
            var client = new WebClient();
            string html = client.DownloadString(SvnUrl);
            var pattern = new Regex(@" - Revision (?<rev>\d+):", RegexOptions.CultureInvariant);
            Match match = pattern.Match(html);
            if (match.Success && match.Groups["rev"].Success) return int.Parse(match.Groups["rev"].Value);
            throw new Exception("Unable to retreive revision!");
        }


        public int LocalRevisionNumber()
        {     
            if(File.Exists(basePath + "King-wow.ver"))
            {
                StreamReader verFile = new StreamReader(basePath + "King-wow.ver");
                string verString = verFile.ReadToEnd();
                verFile.Close();
                int currentRev = int.Parse(verString.Replace("$Revision: ", "").Replace(" $", ""));
                return currentRev;
            }
            else
                return 0;         
        }

        public void WriteLocalRevFile(int newRev)
        {
            Logging.Write("Writing new rev file with " + newRev.ToString());
            StreamWriter file = new StreamWriter(@"" + basePath + "King-wow.ver");
            file.Write("$Revision: " + newRev.ToString() + " $");
            file.Close();
        }

        public void CheckForUpdate()
        {
            try
            {
                int CurrentRevision = LocalRevisionNumber();
                int OnlineRevision = OnlineRevisionNumber();

                Logging.Write("Checking online for King-wow update...");
                if (CurrentRevision < OnlineRevision)
                {
                    Logging.Write("Revision " + OnlineRevision +" is available for download, you are currently using rev " + CurrentRevision);
                    DeleteAll();
                    UpdateFromSvn(new WebClient(), SvnUrl);
                    Logging.Write(" ");
                    Logging.Write("Download of revision " + OnlineRevision +
                                  " is complete. You must close and restart HB for the changes to take effect.");
                    Logging.Write(" ");
                    WriteLocalRevFile(OnlineRevision);
                }
                else
                {
                    Logging.Write("No updates have been found. Revision " + CurrentRevision + " is the latest build.");
                }
            }
            catch
            {
            }
        }

        private string RemoveXmlEscapes(string xml)
        {
            return
                xml.Replace("&amp;", "&").Replace("&lt;", "<").Replace("&gt;", ">").Replace("&quot;", "\"").Replace(
                    "&apos;", "'");
        }

        private void DeleteAll()
        {
            Logging.Write("Deleting old files and directories");
            string basePath = Path.Combine(Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName),
                @"Routines\king-wow\");
            var folderInfo = new DirectoryInfo(basePath);

            foreach (FileInfo file in folderInfo.GetFiles())
            {
                file.Delete();
            }
            foreach (DirectoryInfo dir in folderInfo.GetDirectories())
            {
                dir.Delete(true);
            }
            
            Logging.Write("Cleanup completed!");
        }

        private void UpdateFromSvn(WebClient client, string url)
        {
            string basePath = Path.Combine(Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName),
                @"Routines\king-wow\");
            string html = client.DownloadString(url);
            MatchCollection results = LinkPattern.Matches(html);
            IEnumerable<Match> matches = from match in results.OfType<Match>()
                                         where match.Success && match.Groups["ln"].Success
                                         select match;
            Logging.Write("Downloading new files...... please wait......");
            foreach (Match match in matches)
            {
                string file = RemoveXmlEscapes(match.Groups["ln"].Value);
                string newUrl = url + file;
                if (newUrl[newUrl.Length - 1] == '/') // it's a directory...
                {
                    UpdateFromSvn(client, newUrl);
                }
                else // its a file.
                {
                    string filePath, dirPath;
                    if (url.Length > SvnUrl.Length)
                    {
                        string relativePath = url.Substring(SvnUrl.Length);
                        dirPath = Path.Combine(basePath, relativePath);
                        filePath = Path.Combine(dirPath, file);
                    }
                    else
                    {
                        dirPath = Environment.CurrentDirectory;
                        filePath = Path.Combine(basePath, file);
                    }
                    if (!Directory.Exists(dirPath)) Directory.CreateDirectory(dirPath);
                    client.DownloadFile(newUrl, filePath);
                }
            }
        }




    }
}
